package com.cxl.utils.pdf;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.util.StringUtils;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPRow;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * PDF工具类
 * @author 45466
 *
 */
public class PDFUtils {


	private static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private static String picPath="";

	private static String filePath="";

	private static String inpic="";

	private static BaseFont bfChinese;

	public static String getInpic() {
		return inpic;
	}

	public static String getPicPath() {
		return picPath;
	}

	public static String getFilePath() {
		return filePath;
	}

	private static BaseFont getChinseFont(){
		return bfChinese;
	}

	/**
	 * 获取字体
	 * @return
	 * @throws DocumentException
	 * @throws IOException
	 */
	static    {
		try {
			String fontName = "";
			// 获取操作系统
			String os = System.getProperty("os.name");
			Properties properties = new Properties();
			properties.load(PDFUtils.class.getResourceAsStream("/application-pdf.properties"));
			if (!os.toLowerCase().startsWith("win")) { // linux 操作系统
				fontName = properties.getProperty("linuxfontpath");
				picPath = properties.getProperty("linuxpicpath");
				filePath = properties.getProperty("linuxfilepath");
				inpic = properties.getProperty("linuxinpic");
			} else {
				fontName = properties.getProperty("winfontpath");
				picPath = properties.getProperty("winpicpath");
				filePath = properties.getProperty("winfilepath");
				inpic = properties.getProperty("wininpic");
			}
			System.out.println(" fonteName is " + fontName);
			File file = new File(fontName);
			if (file.exists()) {
				bfChinese = BaseFont.createFont(fontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
				//return bfChinese;
			} else {
				//throw new Exception("没有字体文件：" + fontName);
			}
		}catch (Exception e){
			e.printStackTrace();
		}


	}

	public static Font getFont() throws Exception, DocumentException {
		BaseFont bfChinese = getChinseFont();
		Font myFont = new Font(bfChinese);
		return myFont;
	}

	/**
	 *  使用说明
	 * @throws Exception
	 */
	/*public void testPdf() throws Exception {
		Document document = new Document(); // 不能忽略
		PdfWriter pdfWriter = PDFUtils.createDoc(document, "d:/pdf/mytest21.pdf");//不能忽略
		List<String> list=new ArrayList<String>();
		list.add("张三");
		list.add("李四");
		PDFUtils.addContent(document,list,16);
		//
		ArrayList<com.zhuzhiguang.w3.entity.Goods> list1 = new ArrayList<>();
		list1.add(new com.zhuzhiguang.w3.entity.Goods("3223","电饭锅",new Date(),new URL("https://img0.baidu.com/it/u=3119542616,1165410720&fm=26&fmt=auto")));
		list1.add(new com.zhuzhiguang.w3.entity.Goods("787878","免费",new Date(),new URL("file:///d:/pdf/3.jpg")));

		PDFUtils.addTable(pdfWriter,new String[]{"编号","名称","日期","图片"},new String[]{"isbn","name","expire","imgUrl"},list1,30,600);
		PDFUtils.addImg(document,"D:/事故单/8月/梁刚刚.jpg",30,400,150,150);
		document.close();
		pdfWriter.close();

		PDFUtils.markTxt(new FileInputStream("D:\\pdf\\mytest21.pdf"), new FileOutputStream("d:/pdf/mark.pdf"),"北京八维","朱志广");
		PDFUtils.markImage("d:/pdf/mark.jpg",new FileInputStream("D:\\pdf\\mytest21.pdf"), new FileOutputStream("d:/pdf/markimg.pdf"),"动漫图片");
		PDFUtils.pdf2png("d:/pdf/markimg.pdf","d:/pdf/markimgt.png");

	}*/
	/**
	 * 使用步骤
	 * @param args
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static void main(String[] args) throws Exception, SecurityException, IllegalArgumentException, IllegalAccessException {
		// 1. 生成文档对象-------------
		Document document = new Document(); // 不能忽略
		// 获取输出对象
		try {
			// 生成pdf文件的的路径-----------
			PdfWriter pdfWriter = PDFUtils.createDoc(document, "d:/mytest21.pdf");//不能忽略

			//添加的内容   看实际情况
			List<String> list = new ArrayList<String>();
			list.add("我的标题");
			list.add("这里是正文内容");
			list.add("");
			list.add("价格：" + 1234  + "     单价：" + 13.25);
			// 将list 中的内容添加  到PDF文件当中
			//--------------------
			PDFUtils.addContent(document, list, 18);


			// 添加一个图片   需要就加 不需要就不加------------------
			PDFUtils.addImg(document,"d:/testaaaa.jpg",100,300,300,100);

			// 添加一个表格   看实际情况
			List<Goods> list2 = new ArrayList<Goods>();
			list2.add(new Goods(1,"衣服",12344));
			list2.add(new Goods(2,"袜子",213));
			list2.add(new Goods(3,"腰带",321));
			// 具体添加表格--------------------------------------
			PDFUtils.addTable(pdfWriter,new String[] {"id","名称","价格"},
					new String[] {"id","name","price"}, list2,50,200);

			List<MyKeyValue> arrayList = new ArrayList<MyKeyValue>();
			arrayList.add(new MyKeyValue("价格", 12+""));
			arrayList.add(new MyKeyValue("mingcheng", "wazi"));

			PDFUtils.addTable(pdfWriter,new String[] {"标题","内容"},
					new String[] {"key","value"}, arrayList,50,100);

			// ---------------------
			document.close();// 不能忽略
			// ---------------------
			pdfWriter.close();// 不能忽略


			//将刚才生成的pdf 文件生成一个图片  根据实际情况
			PDFUtils.pdf2png("d:/mytest21.pdf",
					"d:/mytest21png.png");

			//将刚才生成的pdf 添加文字水印   根据实际情况
			PDFUtils.markTxt(new FileInputStream("d:/mytest21.pdf"),
					new FileOutputStream("d:/mytest21marktext.pdf"), "=====", "beijingbawe");

			//将刚才生成的pdf 添加图片水印   根据实际情况
			PDFUtils.markImage("d:/dog.png",
					new FileInputStream("d:/mytest21marktext.pdf"),
					new FileOutputStream("d:/mytest21marktextimg.pdf"), "zhuzhiguang");


		} catch (DocumentException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	/**
	 * 获取文档对象
	 * @throws DocumentException
	 * @throws FileNotFoundException
	 */
	public static PdfWriter createDoc(Document document ,String filePath) throws FileNotFoundException, DocumentException {

		// 2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中。
		// 创建 PdfWriter 对象 第一个参数是对文档对象的引用，第二个参数是文件的实际名称，在该名称中还会给出其输出路径。
		PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePath));
		// 3.打开文档
		document.open();
		return writer;
	}


	/**
	 * 将pdf文件转换成图片
	 * @param pdfFile
	 * @param pngFile
	 * @return
	 */
	public static boolean pdf2png(String pdfFile,String pngFile) {

		System.out.println("开始pdf生成png图片");
		// 将pdf装图片 并且自定义图片得格式大小
		File file = new File(pdfFile);
		try {
			PDDocument doc = PDDocument.load(file);
			PDFRenderer renderer = new PDFRenderer(doc);
			int pageCount = doc.getNumberOfPages();
			for (int i = 0; i < pageCount; i++) {
				BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
				// BufferedImage srcImage = resize(image, 240, 240);//产生缩略图
				ImageIO.write(image, "PNG", new File(pngFile));
				System.out.println("生成png文件：" + pngFile);
			}
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}





	/**
	 *   添加水印
	 * @param is  输入流
	 * @param os  输出流
	 * @param mainMark
	 * @param rootMark
	 * @throws DocumentException
	 * @throws IOException
	 */
	public static void markTxt(InputStream is, OutputStream os, String mainMark, String rootMark)
			throws DocumentException, Exception {
		markTxt(0.2f, 60, true, is, os, mainMark, rootMark);
	}

	/**
	 *      加图片水印
	 * @param iconPath
	 * @param is
	 * @param os
	 * @param rootMark
	 * @throws DocumentException
	 * @throws IOException
	 */
	public static void markImage(String iconPath, InputStream is, OutputStream os, String rootMark)
			throws DocumentException, Exception {
		markImage(iconPath, 0.2f, 60, true, is, os, rootMark);
	}

	/**
	 *
	 * @param alpha        透明度 0-1
	 * @param degree    角度
	 * @param isUnder    水印置于文本上/下
	 * @param is        输入IO
	 * @param os        输出IO
	 * @param mainMark    主文本
	 * @param rootMark    页脚文本
	 */
	private static void markTxt(float alpha, int degree, boolean isUnder, InputStream is, OutputStream os,
								String mainMark, String rootMark) throws DocumentException, Exception {
		PdfReader reader = new PdfReader(is);
		PdfStamper stamper = new PdfStamper(reader, os);

		try {
			PdfGState gs = new PdfGState();
			gs.setFillOpacity(alpha);

			BaseFont base = getChinseFont();

			PdfContentByte content;
			int total = reader.getNumberOfPages() + 1;
			for (int i = 1; i < total; i++) {
				if (isUnder) {
					content = stamper.getUnderContent(i);
				} else {
					content = stamper.getOverContent(i);
				}
				content.setGState(gs);
				content.beginText();
				content.setColorFill(BaseColor.GRAY);
				content.setFontAndSize(base, 64);
				content.setTextMatrix(70, 200);
				content.showTextAligned(Element.ALIGN_CENTER, mainMark, 300, 350, degree);

				content.setColorFill(BaseColor.YELLOW);
				content.setFontAndSize(base, 32);
				content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, degree);
				content.endText();

			}
		} finally {
			stamper.close();
			reader.close();
			is.close();
		}
	}



	/**
	 *
	 * @param iconPath     图标
	 * @param alpha        透明度
	 * @param degree    角度
	 * @param isUnder    在内容下/上方加水印
	 * @param is        输入IO
	 * @param os        输出IO
	 * @param rootMark    页脚文本描述
	 */
	private static void markImage(String iconPath, float alpha, int degree, boolean isUnder, InputStream is,
								  OutputStream os, String rootMark) throws DocumentException, Exception {
		PdfReader reader = new PdfReader(is);
		PdfStamper stamper = new PdfStamper(reader, os);
		try {
			BaseFont base =getChinseFont();

			PdfGState gs = new PdfGState();
			gs.setFillOpacity(alpha);

			PdfContentByte content;
			int total = reader.getNumberOfPages() + 1;
			for (int i = 1; i < total; i++) {
				if (isUnder) {
					content = stamper.getUnderContent(i);
				} else {
					content = stamper.getOverContent(i);
				}

				content.setGState(gs);
				content.beginText();

				Image image = Image.getInstance(iconPath);
				image.setAlignment(Image.LEFT | Image.TEXTWRAP);
				image.setRotationDegrees(degree);
				image.setAbsolutePosition(200, 200);
				image.scaleToFit(400, 400);

				content.addImage(image);
				content.setColorFill(BaseColor.BLACK);
				content.setFontAndSize(base, 64);
				content.showTextAligned(Element.ALIGN_CENTER, rootMark, 100, 100, degree);
				content.endText();
			}
		} finally {
			stamper.close();
			reader.close();
			is.close();
		}
	}




	/**
	 *       向文章中写如内容
	 * @param document
	 * @param list
	 * @param i
	 * @throws DocumentException
	 * @throws IOException
	 */
	public static void addContent(Document document, List<String> list, int i) throws DocumentException, Exception {
		// TODO Auto-generated method stub
		Font myFont = getFont();
		myFont.setSize(i);

		for (String string : list) {
			Paragraph paragraph = new Paragraph(string, myFont);
			document.add(paragraph);
		}
	}




	/**
	 *
	 * @param document
	 * @param imgName
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @throws IOException
	 * @throws MalformedURLException
	 * @throws DocumentException
	 */
	public static void addImg(Document document, String imgName, int x, int y, int width, int height)  {
		// TODO Auto-generated method stub


		// 添加图片
		Image img;
		try {
			img = Image.getInstance(imgName);
			img.setAbsolutePosition(x, y);
			img.scaleAbsolute(width, height);
			document.add(img);
		} catch (IOException | DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.err.println("添加图片失败 " + imgName);
		}

	}


	/**
	 * 添加表格
	 * @param writer
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static void addTable(PdfWriter writer, String[] titles,String[] props, List dataList,int x,int y) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, DocumentException, Exception {
		// TODO Auto-generated method stub
		PdfContentByte content = writer.getDirectContent();
		PdfPTable pTable = new PdfPTable(titles.length);

		BaseFont bfChinese = getChinseFont();
		Font font = new Font(bfChinese);

		ArrayList<PdfPRow> rows = pTable.getRows();
		//第一行是标题
		PdfPCell[] cells = new PdfPCell[titles.length];
		for (int i = 0; i < cells.length; i++) {
			cells[i]=new PdfPCell(new Paragraph(titles[i],font));
		}
		rows.add(new PdfPRow(cells));

		// 中间其他的数据
		for (Object data : dataList) {
			// 存储每行的数组
			PdfPCell[] cells2 = new PdfPCell[titles.length];


			for (int i = 0; i < cells2.length; i++) {
				// 获取data当中某个属性数值
				// 通过反射获取字段
				Field field = data.getClass().getDeclaredField(props[i]);
				if(field!=null  ) {
					//暴力打破封装
					field.setAccessible(true);
					if(field.get(data)!=null ) {
						// 设置内容
						if(field.getType()== Date.class) {
							cells2[i] = new PdfPCell(new Paragraph( sdf.format(field.get(data)) , font));
						}else if(field.get(data) instanceof URL)
							cells2[i] = new PdfPCell(Image.getInstance((URL)field.get(data)),true);
						else {
							cells2[i] = new PdfPCell(new Paragraph(field.get(data).toString(), font));
						}
					}else {
						cells2[i] = new PdfPCell(new Paragraph("",font));
					}
				}else {
					cells2[i] = new PdfPCell(new Paragraph("",font));
				}
			}

			rows.add(new PdfPRow(cells2));


		}
		pTable.setTotalWidth(500);
		pTable.writeSelectedRows(0, 100, x, y, content);

	}






}

class Goods{

	int id;
	String name;
	int price;



	public Goods() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Goods(int id, String name, int price) {
		super();
		this.id = id;
		this.name = name;
		this.price = price;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return "Goods [id=" + id + ", name=" + name + ", price=" + price + "]";
	}



}

class MyKeyValue {

	String key;
	String value;

	public MyKeyValue() {
		super();
	}
	public MyKeyValue(String key, String value) {
		super();
		this.key = key;
		this.value = value;
	}
	public String getKey() {
		return key;
	}
	public void setKey(String key) {
		this.key = key;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}



/*
	@GetMapping(value = "topdf")
	public void topdf(HttpServletResponse response) throws Exception {
		List<Services> list = servicesService.list();
		for (Services services : list) {
			services.setUrl(new URL(PDFUtils.getPicPath() + services.getPicurl()));
		}
		Document document = new Document();
		PdfWriter pdfWriter = PDFUtils.createDoc(document, PDFUtils.getFilePath() + "services.pdf");
		PDFUtils.addTable(pdfWriter,
				new String[]{"ID","头像","昵称"},
				new String[]{"id","url","nickname"},
				list,30,800);
		PDFUtils.addImg(document, PDFUtils.getPicPath() + "1.jpg", 100, 200, 200, 200);
		document.close();
		pdfWriter.close();
		PDFUtils.markImage(PDFUtils.getPicPath() + "2.jpg",
				new FileInputStream(PDFUtils.getFilePath()+"services.pdf"),
				new FileOutputStream(PDFUtils.getFilePath()+"servicesimg.pdf"),
				"这是水印");
		FileUtils.download(response,PDFUtils.getFilePath()+"servicesimg.pdf","do.pdf",0);
	}
*/


}
